#ifndef DATAADAPTERSBASE_H_
#define DATAADAPTERSBASE_H_

namespace scatu {

// Default adapter for C-classes
// Class has to have a NewL()-function
template<typename T>
class RDataAdapter
    {
public:
    typedef T & ArgType; 
    typedef T * ReturnType;
    typedef T const & ReferenceType;
    
    RDataAdapter(ArgType aValue)
      : iData(&aValue), iDataOwned(EFalse) {}

    RDataAdapter(ReturnType aValue)
      : iData(aValue), iDataOwned(ETrue) {}
    
    RDataAdapter()
      : iData(NULL), iDataOwned(EFalse) {}
    
    // Free all resources
    void Close()
        {
        if(iDataOwned) { delete iData; }
        iData = NULL;
        } 
    
    void ExternalizeL(RWriteStream& aStream) const
        {
        if(iData) { aStream << *iData; }
        }
    
    void InternalizeL(RReadStream& aStream)
        {
        Close();
        iData = T::NewL();
        iDataOwned = ETrue;
        aStream >> *iData;
        }
    
    operator ReferenceType () const
        {
        return *iData;
        }
    
    ReturnType AdoptL()
        {
        ReturnType ret = iData;
        iData = NULL;
        return ret;
        }
    
private:
    T * iData;
    TBool iDataOwned;
    };

template<typename T, typename SerializeType>
class RDataAdapterIntegral
    {
public:
    
    typedef T ArgType;
    typedef T ReturnType;
    typedef T const & ReferenceType;
    
    void Close() {}
    
    void ExternalizeL(RWriteStream& aStream) const
        {
        (aStream.*iExtFunc)(iValue);
        }
    
    void InternalizeL(RReadStream& aStream)
        {
        iValue = (aStream.*iIntFunc)();
        }
    
    operator ReferenceType () const
        {
        return iValue;
        }
    
    // No AdoptL for integral types
    
protected:
    typedef void (RWriteStream::*ExternalizeFunction)(SerializeType);
    typedef SerializeType (RReadStream::*InternalizeFunction)();
    
    RDataAdapterIntegral(T aValue, ExternalizeFunction aExtFunc, InternalizeFunction aIntFunc)
      : iValue(aValue)
      , iExtFunc(aExtFunc)
      , iIntFunc(aIntFunc)
      {}
    
    RDataAdapterIntegral(ExternalizeFunction aExtFunc, InternalizeFunction aIntFunc)
      : iValue(0)
      , iExtFunc(aExtFunc)
      , iIntFunc(aIntFunc)
      {}
    
private:
    T iValue;
    ExternalizeFunction iExtFunc;
    InternalizeFunction iIntFunc;
    };

template<typename Des, typename Buf, typename Ptr>
class RDesAdapter
    {
public:
    typedef Des const & ArgType;
    typedef Buf * ReturnType;
    typedef Des const & ReferenceType;
    
    RDesAdapter(ArgType aValue)
      : iConstValue(&aValue), iOwnedValue(NULL)
        {}
    
    RDesAdapter(ReturnType aValue)
      : iConstValue(NULL), iOwnedValue(aValue)
        {}
    
    RDesAdapter()
      : iConstValue(NULL), iOwnedValue(NULL)
        {}
    
    void Close()
        {
        delete iOwnedValue;
        iOwnedValue = NULL;
        }
    
    void ExternalizeL(RWriteStream& aStream) const
        {
        Des const * des = iConstValue ? iConstValue : iOwnedValue;
        if(!des) { User::Leave(KErrNotReady); }
        aStream.WriteInt32L(des->Length());
        aStream.WriteL(*des);
        }
    
    void InternalizeL(RReadStream& aStream)
        {
        if(iConstValue) { iConstValue = NULL; }
        delete iOwnedValue;
        iOwnedValue = NULL;
        
        TInt length = aStream.ReadInt32L();
        iOwnedValue = Buf::NewL(length);
        Ptr ptr = iOwnedValue->Des();
        aStream.ReadL(ptr, length);
        }
    
    operator ReferenceType () const
        {
        Des const * des = iConstValue ? iConstValue : iOwnedValue;
        if(!des) { User::Leave(KErrNotReady); }
        return *des;
        }
    
    ReturnType AdoptL()
        {
        Buf * ret = iOwnedValue;
        iOwnedValue = NULL;
        return ret;
        }
    
protected:
    Des const * iConstValue;
    Buf * iOwnedValue;
    };

} // namespace

#endif /* DATAADAPTERSBASE_H_ */
